home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ddj0290.arc / LIAO.LST < prev    next >
File List  |  1990-01-07  |  14KB  |  396 lines

  1. _SELF-ADJUSTING DATA STRUCTURES_
  2. by Andrew M. Liao
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. {*** Singly linked move-to-the front list ***}
  8. {*** Contents: "LInsert", "Mtffind" ***}
  9.  
  10. { Data Structure:
  11.   ptr=^node;
  12.   node=RECORD rec:item; next:ptr; END;  }
  13.  
  14. PROCEDURE LInsert(arg:item; VAR root:ptr);
  15.     VAR p:ptr;                          { To generate storage }
  16.     BEGIN
  17.       NEW(p);                           { Allocate }
  18.       p^.rec:=arg;                      { Add data }
  19.       p^.next:=root;                    { Place at front of list }
  20.       root:=p;                          { Point to new front of list }
  21.     END;
  22.  
  23. FUNCTION Mtffind(arg:item; VAR root:ptr;):boolean;
  24.     VAR temp1,temp2:ptr;                   { Search pointers }
  25.         found:boolean;                     { TRUE iff found }
  26.     BEGIN
  27.       temp1:=root;                         { Get a copy of starting location }
  28.       temp2:=root;                         { Secondary copy }
  29.       found:=false;                        { Nothing found yet }
  30.  
  31.       WHILE (temp1<>NIL) AND (NOT found) DO
  32.           BEGIN
  33.             IF temp1^.rec<>arg THEN        { Found it? }
  34.                 BEGIN                      { Nope... }
  35.                   temp2:=temp1;            { Move trailing pointer }
  36.                   temp1:=temp1^.next;      { Move search pointer }
  37.                 END
  38.             ELSE found:=true;              { Yup... }
  39.           END;
  40.  
  41.       IF found THEN                        { Move item to front of list }
  42.           BEGIN
  43.             temp2^.next:=temp1^.next;
  44.             IF temp1<>root THEN temp1^.next:=root;
  45.             root:=temp1;
  46.           END;
  47.  
  48.       Mtffind:=found;
  49.     END;
  50.  
  51.  
  52. [LISTING TWO]
  53.  
  54. {*** Move To The Front Splay Tree ***}
  55. {*** Contents: SplaySearch, BSInsert, BSDelete ***}
  56.  
  57. { Data Structure:
  58.   ptr=^node;
  59.   node=RECORD data:key; left,right:ptr; END;    }
  60.  
  61. FUNCTION SplaySearch(x:key; VAR p:ptr):boolean;
  62. TYPE noderec=RECORD                     { Temporary Tree Pointer Def. }
  63.                left,right:ptr;
  64.              END;
  65. VAR l,r:noderec;                        { Temporary Trees }
  66.     done:boolean;                       { TRUE if NIL encountered in search }
  67.  
  68.   PROCEDURE RRot(VAR p:ptr);
  69.     VAR temp,temp1:ptr;                 { Temporary pointers }
  70.     BEGIN
  71.       IF p<>NIL THEN                    { Don't rotate if nothing's there }
  72.         IF p^.left<>NIL THEN            { No left edge - don't rotate }
  73.           BEGIN
  74.             temp:=p; temp1:=p^.left^.right;  { Copy root & 2ndary child }
  75.             p:=temp^.left; p^.right:=temp;   { Rotate root }
  76.             temp^.left:=temp1;         { Reattach 2ndary child }
  77.           END;
  78.     END;
  79.  
  80.   PROCEDURE LRot(VAR p:ptr);
  81.     VAR temp,temp1:ptr;                 { Temporary pointers }
  82.     BEGIN
  83.       IF p<>NIL THEN                    { Don't rotate if nothing's there }
  84.         IF p^.right<>NIL THEN           { No right edge - don't rotate }
  85.           BEGIN
  86.             temp:=p; temp1:=p^.right^.left;  { Copy root & 2ndary child }
  87.             p:=temp^.right; p^.left:=temp;   { Rotate root }
  88.             temp^.right:=temp1;        { Reattach 2ndary child }
  89.           END;
  90.     END;
  91.  
  92.   PROCEDURE LnkRight(VAR p:ptr; VAR r:noderec);
  93.     VAR temp:ptr;                       { Temporary pointer }
  94.     BEGIN
  95.       IF p^.left<>NIL THEN              { No left child - don't cut & link }
  96.         BEGIN
  97.           temp:=p^.left; p^.left:=NIL;  { Remember left child & break link }
  98.           IF r.left=NIL THEN            { Attach to temporary tree }
  99.             BEGIN r.left:=p; r.right:=p;END { Empty tree? }
  100.           ELSE                          { Just add to bottom leftmost }
  101.             BEGIN r.right^.left:=p; r.right:=r.right^.left; END;
  102.           p:=temp;                      { New root is left child }
  103.         END;
  104.     END;
  105.  
  106.   PROCEDURE LnkLeft(VAR p:ptr; VAR l:noderec);
  107.     VAR temp:ptr;                       { Temporary pointer }
  108.     BEGIN
  109.       IF p^.right<>NIL THEN             { No right child - don't cut & link }
  110.         BEGIN
  111.           temp:=p^.right; p^.right:=NIL;{ Remember right child & break link }
  112.           IF l.left=NIL THEN            { Attach to temporary tree }
  113.             BEGIN l.left:=p; l.right:=p;END { Empty tree? }
  114.           ELSE                          { Just add to bottom rightmost }
  115.             BEGIN l.right^.right:=p; l.right:=l.right^.right; END;
  116.           p:=temp;                      { New root is right child }
  117.         END;
  118.     END;
  119.  
  120.   PROCEDURE Assemble(VAR p:ptr; VAR l,r:noderec);
  121.     VAR temp,temp1:ptr;
  122.     BEGIN
  123.       temp:=p^.left; temp1:=p^.right;   { Hold onto subtrees }
  124.       IF l.left<>NIL THEN
  125.         BEGIN
  126.           p^.left:=l.left;              { Attach temporary left subtree }
  127.           l.right^.right:=temp;         { Reattach orginal left subtree }
  128.         END;
  129.       IF r.left<>NIL THEN
  130.         BEGIN
  131.           p^.right:=r.left;             { Attach temporary right subtree }
  132.           r.right^.left:=temp1;         { Reattach original right subtree }
  133.         END;
  134.     END;
  135.  
  136.   BEGIN
  137.     l.left:=NIL; l.right:=NIL;          { Initialize temp trees }
  138.     r.left:=NIL; r.right:=NIL;
  139.     done:=false;                        { Init to "item maybe there" }
  140.     IF p<>NIL THEN                      { No search if tree's empty }
  141.       BEGIN
  142.       REPEAT
  143.         IF (x<p^.data) THEN             { Item on left subtree? }
  144.           IF (p^.left<>NIL) THEN
  145.             BEGIN
  146.               IF x=p^.left^.data THEN LNKRIGHT(p,r)
  147.               ELSE
  148.               IF x<p^.left^.data THEN BEGIN RRot(p); LNKRIGHT(p,r); END
  149.               ELSE
  150.               IF x>p^.left^.data THEN BEGIN LNKRIGHT(p,r);LNKLEFT(p,l);END;
  151.             END ELSE done:=TRUE
  152.         ELSE
  153.         IF (x>p^.data) THEN             { Item on right subtree? }
  154.           IF (p^.right<>NIL) THEN
  155.             BEGIN
  156.               IF x=p^.right^.data THEN LNKLEFT(p,l)
  157.               ELSE
  158.               IF x>p^.right^.data THEN BEGIN LRot(p); LNKLEFT(p,l); END
  159.               ELSE
  160.               IF x<p^.right^.data THEN BEGIN LNKLEFT(p,l);LNKRIGHT(p,r);END;
  161.             END ELSE done:=TRUE;
  162.       UNTIL (x=p^.data) OR DONE;
  163.       ASSEMBLE(p,l,r); SplaySearch:=(x=p^.data);
  164.     END ELSE SplaySearch:=FALSE;
  165.   END;
  166.  
  167. PROCEDURE BSInsert(x:key; VAR root:ptr);
  168. VAR p:ptr;
  169. BEGIN
  170.   NEW(p);
  171.   p^.data:=x;
  172.   p^.left:=NIL; p^.right:=NIL;
  173.   IF root=NIL THEN root:=p                      { No tree, just insert }
  174.   ELSE
  175.   BEGIN
  176.     IF NOT SplaySearch(x,root) THEN             { Is it already there? }
  177.       IF x<root^.data THEN                      { Less than? }
  178.         BEGIN
  179.           p^.right:=root;                       { Root item greater than }
  180.           p^.left:=root^.left;                  { Link up left child }
  181.           root^.left:=NIL; root:=p;             { Break link; root=new item }
  182.         END
  183.       ELSE
  184.       IF x>root^.data THEN                      { Greater than? }
  185.         BEGIN
  186.           p^.left:=root;                        { Root item less than }
  187.           p^.right:=root^.right;                { Link up right child }
  188.           root^.right:=NIL; root:=p;            { Break link; root=new item }
  189.         END;
  190.   END;
  191. END;
  192.  
  193. PROCEDURE BSDelete(x:key; VAR root:ptr);
  194. VAR temp1,temp2,temp4:ptr;
  195.     temp3:key;
  196.     flg:boolean;
  197. BEGIN
  198.   IF SplaySearch(x,root) THEN
  199.     BEGIN
  200.       temp1:=root^.left; temp2:=root^.right;    { Save subtrees }
  201.       IF temp1<>NIL THEN                        { Is there a left subtree? }
  202.         BEGIN
  203.           temp4:=temp1;
  204.           WHILE temp4^.right<>NIL DO            { MTF max left tree element }
  205.             temp4:=temp4^.right;
  206.           temp3:=temp4^.right^.data;
  207.           flg:=SplaySearch(temp3,temp1);
  208.           temp1^.right:=temp2;                  { Attach right subtree }
  209.         END ELSE temp1:=temp2;                  { Just attach right tree }
  210.        dispose(root);
  211.        root:=temp1;                             { Return new tree }
  212.     END;
  213. END;
  214.  
  215.  
  216. [LISTING THREE]
  217.  
  218. {*** Self-adjusting heap ***}
  219. {*** Contents: Merge, Min, Insert, DeleteMin routines ***}
  220.  
  221. { Data Structure:
  222.   ptr=^node;
  223.   node=RECORD data:item; left,right:ptr; END;   }
  224.  
  225. FUNCTION Merge(q1,q2:ptr):ptr;
  226.   TYPE Qrec=RECORD
  227.                 front,rear:ptr;
  228.             END;
  229.   VAR Q:Qrec;
  230.   PROCEDURE Enqueue(VAR q1:ptr; VAR Q:Qrec);
  231.     VAR temp:ptr;
  232.     BEGIN
  233.       temp:=q1;                         { Save top of heap }
  234.       q1:=q1^.right;                    { Point to next top of heap }
  235.       temp^.right:=temp^.left;          { Swap right child to left }
  236.       temp^.left:=NIL;                  { Make sure left link's broken }
  237.       IF q.front=NIL THEN               { Empty merge queue }
  238.         BEGIN
  239.           q.front:=temp; q.rear:=temp;
  240.         END
  241.       ELSE                              { Oops, just add to last leftchild }
  242.         BEGIN
  243.           q.rear^.left:=temp; q.rear:=temp;
  244.         END;
  245.     END;
  246.   BEGIN
  247.     q.front:=NIL; q.rear:=NIL;          { Init merge queue }
  248.     WHILE (q1<>NIL) AND (q2<>NIL) DO    { Pairwise compare and merge }
  249.         IF q1^.data<=q2^.data THEN Enqueue(q1,q)
  250.         ELSE Enqueue(q2,q);
  251.  
  252.     IF (q1<>NIL) AND (q2=NIL) THEN
  253.       BEGIN
  254.         IF q.rear<>NIL THEN q.rear^.left:=q1
  255.         ELSE q.front:=q1;
  256.       END
  257.     IF (q1=NIL) AND (q2<>NIL) THEN
  258.       BEGIN
  259.         IF q.rear<>NIL THEN q.rear^.left:=q2
  260.         ELSE q.front:=q2;
  261.       END;
  262.     Merge:=q.front;
  263.   END;
  264.  
  265. FUNCTION Min(q1:ptr; VAR x:ptr):boolean;
  266.   BEGIN
  267.     x:=q1;
  268.     Min:=(q1<>NIL);
  269.   END;
  270.  
  271. PROCEDURE Insert(x:item; VAR q:ptr);
  272.   VAR p:ptr;
  273.   BEGIN
  274.     NEW(p);                             { Allocate }
  275.     p^.data:=x;                         { Fill it! }
  276.     p^.left:=NIL; p^.right:=NIL;        { No children }
  277.     q:=Merge(q,p);                      { Add it to heap }
  278.   END;
  279.  
  280. FUNCTION DeleteMin(q:ptr; VAR x:ptr):ptr;
  281.   BEGIN
  282.     IF Min(q,x) THEN                    { Is there a min to delete? }
  283.       DeleteMin:=Merge(q^.left,q^.right)
  284.     ELSE DeleteMin:=NIL;                { Nothing at all }
  285.   END;
  286.  
  287. { Pairing Heaps as described by Tarjan, et al from Algorithmica:
  288.   Data Structure:
  289.   TYPE hptr=^node;
  290.        node=RECORD
  291.               wt:integer;
  292.               parent,left,right:hptr;
  293.             END;                        }
  294.  
  295. FUNCTION Merge(arg1,arg2:hptr):hptr;
  296. BEGIN
  297.   IF (arg1<>NIL) AND (arg2<>NIL) THEN           { 2 Queues to merge? }
  298.     BEGIN
  299.       IF arg1^.wt<arg2^.wt THEN         { Which is minimal? }
  300.         BEGIN
  301.           arg2^.parent:=arg1;                   { Who's the parent? }
  302.           arg2^.right:=arg1^.left;              { Point to arg1's child }
  303.           arg1^.left:=arg2;                     { It's officially a child }
  304.           Merge:=arg1;
  305.         END
  306.       ELSE
  307.         BEGIN
  308.           arg1^.parent:=arg2;                   { Who's the parent? }
  309.           arg1^.right:=arg2^.left;              { Point to arg2's child }
  310.           arg2^.left:=arg1;                     { It's officially a child }
  311.           Merge:=arg2;
  312.         END;
  313.      END
  314.    ELSE
  315.    IF (arg1<>NIL) THEN Merge:=arg1              { Just arg1's queue }
  316.    ELSE Merge:=arg2                             { Anything else }
  317. END;
  318.  
  319. PROCEDURE Insert(a1,a2,x:integer; VAR root:hptr);
  320. VAR p:hptr;
  321. BEGIN
  322.   New(p);                                       { Allocate }
  323.   p^.v1:=a1; p^.v2:=a2;
  324.   p^.wt:=x;  p^.parent:=NIL;                    { Set key }
  325.   p^.left:=NIL; p^.right:=NIL;                  { Set pointers }
  326.   root:=Merge(p,root);                          { Add it... }
  327. END;
  328.  
  329. FUNCTION Min(root:hptr; VAR minitem:hptr):boolean;
  330. BEGIN
  331.   minitem:=root;                                { What's at the root? }
  332.   Min:=(minitem<>NIL);                          { Anything there? }
  333. END;
  334.  
  335. FUNCTION DeleteMin(root:hptr; VAR minitem:hptr):hptr;
  336. VAR arg1,arg2,p1:hptr;
  337. BEGIN
  338.   IF Min(root,minitem) THEN
  339.     BEGIN
  340.       root:=NIL;                                { ReInit root }
  341.       p1:=minitem^.left;                        { Save kids }
  342.       WHILE p1<>NIL DO                          { For all subtrees }
  343.         BEGIN
  344.           arg1:=p1;                             { First Subtree }
  345.           p1:=p1^.right;                        { Move along }
  346.           arg2:=p1;                             { Next potential subtree }
  347.           IF p1<>NIL THEN p1:=p1^.right;        { If not NIL, move on }
  348.           root:=Merge(Merge(arg1,arg2),root);   { Merge result with current }
  349.         END;
  350.        IF root<>NIL THEN root^.right:=NIL;
  351.        DeleteMin:=root;
  352.     END ELSE DeleteMin:=NIL;
  353. END;
  354.  
  355. FUNCTION LinkSearch(p:hptr):hptr;
  356. VAR temp:hptr;
  357. BEGIN
  358.   temp:=p^.parent^.left;
  359.   WHILE (temp<>p) AND (temp^.right<>p) AND (temp^.right<>NIL) DO
  360.     temp:=temp^.right;
  361.   LinkSearch:=temp;
  362. END;
  363.  
  364. FUNCTION DecreaseKey(change:integer; p,root:hptr):hptr;
  365. VAR temp:hptr;
  366. BEGIN
  367.   IF (p<>NIL) AND (root<>NIL) THEN
  368.     BEGIN
  369.       p^.wt:=p^.wt-ABS(change);
  370.       IF p=root THEN DecreaseKey:=root
  371.       ELSE
  372.       BEGIN
  373.         temp:=LinkSearch(p);
  374.         IF temp=p THEN p^.parent^.left:=p^.parent^.left^.right
  375.         ELSE temp^.right:=p^.right;
  376.         DecreaseKey:=Merge(p,root);
  377.       END;
  378.     END;
  379. END;
  380.  
  381. FUNCTION Delete(p,root:hptr):hptr;
  382. VAR temp:hptr;
  383. BEGIN
  384.   IF (p<>NIL) AND (root<>NIL) THEN
  385.     BEGIN
  386.       IF p=root THEN Delete:=DeleteMin(root,temp)
  387.       ELSE
  388.       BEGIN
  389.         temp:=LinkSearch(p);
  390.         IF temp=p THEN p^.parent^.left:=p^.parent^.left^.right
  391.         ELSE temp^.right:=p^.right;
  392.         Delete:=Merge(DeleteMin(p,temp),root);
  393.       END;
  394.     END ELSE Delete:=root;
  395. END;
  396.